package com.dimld.connect.http;

import com.dimld.connect.ConnectorI;
import com.dimld.connect.ConnectContainer;
import com.dimld.connect.MsgReaderI;
import io.undertow.io.Receiver;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HeaderMap;
import io.undertow.util.Headers;
import io.undertow.util.HttpString;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.util.Timer;
import java.util.UUID;

@Slf4j
public class HttpHandle implements ConnectorI, Serializable, Receiver.FullBytesCallback {
    private final transient Logger     httpLog         = LoggerFactory.getLogger("http");
    @Getter
    private                 MsgReaderI msgReaderI;
    private                 String     serviceUUID;
    @Getter
    private final           String     uuid            = UUID.randomUUID().toString();
    @Getter
    private                 long       createTimestamp = 0;
    @Getter
    @Setter
    private                 String     bindServiceUuid;
    @Getter
    @Setter
    private                 boolean    state;
    @Getter
    @Setter
    private                 Object     data;

    private           int                timeout;
    private transient Timer              timer;
    @Getter
    private           HttpServerExchange exchange;

    public HttpHandle(HttpServerExchange httpServerExchange, MsgReaderI msgReaderI, int timeout, String serviceUUID) throws IllegalAccessException, InstantiationException {
        this.exchange = httpServerExchange;
        this.msgReaderI = msgReaderI;
        this.timeout = timeout;
        this.createTimestamp = System.currentTimeMillis();
        this.serviceUUID = serviceUUID;
    }

    @Override
    public void send(String receiveMsg) {
        if (this.exchange != null) {
            exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "application/json");
            exchange.getResponseSender().send(receiveMsg);
            this.httpLog.debug("[" + this.exchange.getHostAndPort() + "]发送消息：\n" + receiveMsg);
        } else {
            this.httpLog.debug("[HTTP]response is null");
        }
    }

    public String getConnType() {
        return "HTTP";
    }

    @Override
    public MsgReaderI getReader() {
        return null;
    }

    public boolean isConnected() {
        return this.state;
    }

    public String getFullIP() {
        if (this.exchange != null) {
            return this.exchange.getHostAndPort();
        }
        return "";
    }

    public void shutdown() {
        Thread.currentThread().interrupt();
    }

    public void close() {
        this.timer.cancel();
        shutdown();
        setState(false);
        if (getReader() != null) {
            getReader().disconnect(this);
        }
        ConnectContainer.remove(getUuid());
    }

    public HeaderMap getAllHeader() {
        return this.exchange.getRequestHeaders();
    }

    @Override
    public void handle(HttpServerExchange exchange, byte[] message) {
        HttpString requestMethod = exchange.getRequestMethod();
        String     requestURI    = exchange.getRequestURI();
        String     requestURL    = exchange.getRequestURL();

        log.debug("requestMethod = {}", requestMethod);
        log.debug("requestURI = {}", requestURI);
        log.debug("requestURL = {}", requestURL);
        Thread.currentThread().setName("HttpHandle_" + uuid);
        this.state = true;
        this.timer = new Timer();
        ClearTask t = new ClearTask(this.timer, this, Thread.currentThread().getName(), this);
        this.timer.schedule(t, timeout * 1000L);
        long runStartTime = System.currentTimeMillis();
        ConnectContainer.put(this);
        try {
            String body = new String(message, StandardCharsets.UTF_8);
            this.httpLog.debug("[" + this.getFullIP() + "]收到消息:" + body);
            if (this.msgReaderI != null)
                this.msgReaderI.read(body, this);
            else {
                send("ok");
            }
            this.httpLog.debug("[HTTP]执行时长" + (System.currentTimeMillis() - runStartTime) + "ms");
            this.state = false;
            if (this.msgReaderI != null)
                this.msgReaderI.disconnect(this);
        } catch (Exception e) {
            this.httpLog.error("[HTTP]ִ执行异常", e);
        }
        ConnectContainer.remove(this.uuid);
        this.timer.cancel();
    }
}